<?php

	// +----------------------------------------------------------------------
	// | 附件模型
	// +----------------------------------------------------------------------
	// | Copyright (c) 2015-2024 http://www.yicmf.com, All rights reserved.
	// +----------------------------------------------------------------------
	// | Author: 微尘 <yicmf@qq.com>
	// +----------------------------------------------------------------------

	namespace app\event\file;

	use app\common\event\Job;
    use PhpOffice\PhpSpreadsheet\IOFactory;
    use think\Exception;
	use think\exception\ValidateException;
	use think\facade\Event;
	use think\facade\Filesystem;
	use think\Image;
	use think\facade\Log;
	use think\File;
	use think\facade\Config;
	use app\model\file\Attachment as AttachmentModel;
	use think\facade\Env;
	use Qiniu\Auth as QuniuAuth;
	use Qiniu\Storage\UploadManager as QiniuUploadManager;
	use yicmf\tools\HttpService;

	class Attachment extends Common
	{



        public function generateZip($files_dir, $zip_name = null)
        {
            $toDir = public_path() . 'upload/zip/temp/' . time_format(time(), 'Ym/d/');
            if (!is_dir($toDir)) {
                mkdir($toDir, 0755, true);
            }
            if (is_null($zip_name))
            {
                $zip_name = uniqid().'.zip';
            }
            if (is_file($files_dir))
            {
                $files[] = $files_dir;
            }else{
                // 扫描$con目录下的所有文件
                $files = [];
                foreach(scandir($files_dir) as $k=>$v){
                    // 跳过两个特殊目录   continue跳出循环
                    if($v=="." || $v==".."){continue;}
                    $files[] = $files_dir.$v;
                }

            }
            $zip = new \ZipArchive;
            if ($zip->open($toDir.$zip_name, \ZipArchive::CREATE) === true)
            {
                foreach($files as $k=>$v){
                    $basename = pathinfo($v)['basename'];
                    $zip->addFile($v,$basename);
                }
                // 关闭zip文件
                $zip->close();
            }
            return $toDir.$zip_name;
        }

        public function uploadUrl($url)
		{
			$path = $this->downLoad_pic($url);
			$file = new File($path);
			$data = [];
			$data['md5'] = $file->hash('md5');
			$data['sha1'] = $file->hash('sha1');
			//        $data['driver'] = $setting['driver'];
			$data['name'] = $file->getInfo('name');
			$data['remark'] = $file->getInfo('name');
			$data['size'] = $file->getInfo('size');
			$data['mime'] = $file->getMime();
			$data['path'] = $path;
			$data['ext'] = pathinfo($path, PATHINFO_EXTENSION);
			$data['save_name'] = pathinfo($path, PATHINFO_BASENAME);
			$data['save_path'] = pathinfo($path, PATHINFO_DIRNAME);
			$attachment = ImageModel::create($data);
			if (!$attachment) {
				throw new \Exception('保存图片信息失败');
			}
			$result = [
				'code' => 0,
				'data' => $attachment
			];
			return $result;
		}

		protected function downLoad_pic($url)
		{
			if ($url == "") {
				return false;
			}
			$filename = uniqid() . '.png';
			// 检查路径是否存在，如不存在则创建
			$dir = app()->getRootPath() . 'public/uploads/attachment/' . time_format(time(), 'Y/m/d/');
			$dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
			if (!is_dir($dir)) {
				//第三个参数是“true”表示能创建多级目录，iconv防止中文目录乱码
				mkdir(iconv("UTF-8", "GBK", $dir), 0777, true);
			}
			ob_start();
			readfile($url);
			$img = ob_get_contents();
			ob_end_clean();
			$fp2 = fopen($dir . $filename, "a");
			if (fwrite($fp2, $img) === false) {
				throw new Exception('无法写入图片');
			}
			fclose($fp2);
			return $dir . $filename;
		}

		/**
		 * 上传文件
		 * @param $file
		 * @author  : 微尘 <yicmf@qq.com>
		 * @datetime: 2019/1/11 22:02
		 */
		public function uploadByMaterial($str, $filename)
		{
			//        $filename = Env::get('app_path').'file'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'upload_attachment.php';
			//        $setting = include $filename;
			if (IS_SAFE_MODE) {
				$dir = app()->getRootPath() . 'public' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'attachment' . DIRECTORY_SEPARATOR . time_format(time(), 'ymd') . DIRECTORY_SEPARATOR;
			} else {
				$dir = app()->getRootPath() . 'uploads' . DIRECTORY_SEPARATOR . 'attachment' . DIRECTORY_SEPARATOR . time_format(time(), 'ymd') . DIRECTORY_SEPARATOR;
			}
			if (!is_dir($dir)) {
				//第三个参数是“true”表示能创建多级目录，iconv防止中文目录乱码
				mkdir(iconv("UTF-8", "GBK", $dir), 0777, true);
			}
			$resource = fopen($dir . $filename, 'a');
			fwrite($resource, $str);
			fclose($resource);
			$file = new File($dir . $filename);
			$insert['md5'] = $file->hash('md5');
			$insert['sha1'] = $file->hash('sha1');
			$insert['driver'] = 'loacl';
			$insert['remark'] = $filename;
			$insert['path'] = $dir . $filename;
			$insert['save_path'] = dirname(realpath($insert['path']));
			$insert['save_name'] = $filename;
			$insert['mime'] = $file->getMime();
			$insert['name'] = $filename;
			$insert['ext'] = $file->getExtension();
			$data = AttachmentModel::create($insert);
			$res['code'] = 0;
			$res['data'] = $data;
			return $res;
		}

		/**
		 * 上传文件
		 * @param $file
		 * @author  : 微尘 <yicmf@qq.com>
		 * @datetime: 2019/1/11 22:02
		 */
		public function uploadByFile($file)
		{
			$filename = Env::get('app_path') . 'file' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'upload_attachment.php';
			$setting = include $filename;
			return $this->upload([], $file, $setting);
		}

		/**
		 * 文件上传.
		 * @param array $param post信息
		 * @param File $attachment 要上传的文件列表（需要使用request获取的请求）
		 * @param 0|1 $is_editor  是否为编辑器
		 * @return array 文件上传成功后的信息
		 */
		public function upload($param, $file, $user = null, $is_editor = 0)
		{
			try {
				if (!is_object($file)) {
					// 上传失败获取错误信息
					throw new Exception('上传信息错误');
				}

				$attachment = AttachmentModel::where('md5', $file->md5())->where('status', 1)->find();
				if (!$this->_checkFile($attachment)) {
					/* 图片预处理 --- 上传文件 */
					$data = $this->_dealUpload($param, $file, $is_editor);
					$user && $data['user_id'] = $user['id'];
					$data = array_merge($data, $this->_distinguish($param, $data));
					$attachment = AttachmentModel::create($data);
					if (!$attachment) {
						throw new Exception('保存附件信息失败');
					}
					// 同步cdn
					if ($data['driver'] !== 'local') {
						Job::addTask('sync_image_cdn', ['image_id' => $data['id'], 'param' => $param]);
					}
				} else {
					// 复制一份
					$attachment = $attachment->toArray();
					if ($user && $attachment['user_id'] != $user['id']) {
						$attachment['user_id'] = $user['id'];
						unset($attachment['id']);
						$attachment = AttachmentModel::create($attachment);
					}
				}

				Log::record($attachment);

				// 提交事务
				$result['code'] = 0;
				$result['data'] = $attachment;
			} catch (\Exception $e) {
				// 回滚事务
				$result['code'] = $e->getCode() == 60001 ? 60001 : 1;

				$result['line'] = $e->getLine();
				$result['file'] = $e->getFile();
				$result['message'] = $e->getMessage();
			}
			return $result;
		}

		/**
		 * 附件上传
		 * @param $param
		 * @param $file
		 * @param $is_editor
		 * @return array|void
		 * @throws Exception
		 */
		protected function _dealUpload($param, $file, $is_editor)
		{
			$setting = Config::get('upload_attachment');
            $uploadDir = '';
			if (isset($param['chunks']) && $param['totalPage'] > 1) {
				// 分片上传
				if (!$param['save_path']) {
					$save_path = str_replace('/', DIRECTORY_SEPARATOR, time_format(time(), 'Ym/d') . DIRECTORY_SEPARATOR);
					if (!$param['fileExt']) {
						$path = $save_path . uniqid();
					} else {
						$path = $save_path . uniqid() . '.' . $param['fileExt'];
					}
					$uploadDir = pathinfo(public_path() .$setting['save_path'] . $path)['dirname'];
					if (!is_dir($uploadDir)) {
						mkdir($uploadDir, 0755, true);
					}
				} else {
					$path = $param['save_path'];
				}
				if ($param['page'] == 1) {
					file_put_contents(public_path() . $setting['save_path'] . $path, file_get_contents($file));
				} else {
					//其余文件追加到文件末尾
					file_put_contents(public_path() . $setting['save_path'] . $path, file_get_contents($file), FILE_APPEND);
				}
				//最后一片文件
				if ($param['totalPage'] != $param['page']) {
					throw new Exception($path, 60001);
				}

//				$file = new File(public_path() . $setting['save_path'] . $path);
				$insert = $this->_formatInfo($file,$setting,$uploadDir);
				$insert['path'] = $setting['save_path'] . $path;
				$insert['save_name'] = pathinfo($insert['path'])['filename'];
				$insert['save_path'] = pathinfo($insert['path'])['dirname'];
				$insert['ext'] = pathinfo($insert['path'])['extension'];
				$insert['remark'] = $param['fileName'];

			} else {
				// 正常上传
				$insert = $this->_formatInfo($file,$setting,$uploadDir);
				$re = $file->move($uploadDir, $insert['save_name']);
				if (!$re) {
					throw new Exception('保存异常');
				}
//				try {
//					$setting['max_size'] != 0 && $validate['fileSize'] = $setting['max_size'] * 1024 * 1024;
//					$validate['fileExt'] = $setting['ext'];
//					$validate['fileMime'] = $setting['mimes'];
////				$validate['image'] = $setting['mimes'];
//					validate(['image' => $validate])->check(['image' => $file]);
//				} catch (ValidateException $e) {
//					// 验证失败 输出错误信息
//					throw new Exception($e->getError());
//				}
			}
			return $insert;
		}

		protected function _checkFile($file)
		{
			if ($file) {
				if (is_file($file['path'])) {
					return true;
				} else {
					// 删除模型
					$file->delete();
				}
			}
			return false;
		}

		/**
		 * 解析信息
		 * @throws \Exception
		 */
		protected function _distinguish($param, $data)
		{
			if ('mp3' == $data['ext']) {
				// 解析音频长度
//				require_once(app()->getRootPath() . '/extend/getID3/getid3/getid3.php');
//				$getID3 = new \getID3();    //实例化类
//				$FileInfo = $getID3->analyze($data['path']); //分析文件，$path为音频文件的地址
//				if (isset($FileInfo['playtime_seconds'])) {
//					$data['duration'] = $FileInfo['playtime_seconds'];
//				}
			}elseif (in_array($data['ext'], array('csv', 'mpeg'))) {
//                $reader = IOFactory::createReader('Csv');
//                # 打开文件、载入excel表格
//                $spreadsheet = $reader->load($data['path']);
//                # 获取活动工作薄
//                $sheet = $spreadsheet->getActiveSheet();
//                $highestRow = $sheet->getHighestRow(); // 取得总行数
//                $col = ord($sheet->getHighestColumn()) - ord('A'); // 取得总列数
//                $exc_arr = [];
//                for ($i = 1; $i <= $highestRow; $i++) {
//                    $start = ord('A');
//                    $temp = [];
//                    for ($k = 0; $k <= $col; $k++) {
//                        $temp[] = (string)$spreadsheet->getActiveSheet()->getCell(chr($start) . $i)->getValue(); //读取类型正常
//                        $start++;
//                    }
//                    $exc_arr[] = $temp;
//                }
//                $data['info'] = $exc_arr;
            }
            return $data;
		}
		/**
		 * 解析信息
		 * @throws \Exception
		 */
		public static function distinguish($id)
		{
            $data = AttachmentModel::where('id', $id)->find();

			if ('mp3' == $data['ext']) {
				// 解析音频长度
//				require_once(app()->getRootPath() . '/extend/getID3/getid3/getid3.php');
//				$getID3 = new \getID3();    //实例化类
//				$FileInfo = $getID3->analyze($data['path']); //分析文件，$path为音频文件的地址
//				if (isset($FileInfo['playtime_seconds'])) {
//					$data['duration'] = $FileInfo['playtime_seconds'];
//				}

			}elseif (in_array($data['ext'], array('csv', 'xls','xlsx'))) {
                $reader = IOFactory::createReader(ucfirst($data['ext']));
                if ('csv' == $data['ext']) {
                    $reader->setInputEncoding('GB2312');
                }
                # 打开文件、载入excel表格
                $spreadsheet = $reader->load($data['path']);
                # 获取活动工作薄
                $sheet = $spreadsheet->getActiveSheet();
//                dump($sheet);
//                dump($spreadsheet);
                $highestRow = $sheet->getHighestRow(); // 取得总行数

                $col = ord($sheet->getHighestColumn()) - ord('A'); // 取得总列数
                $exc_arr = [];
                for ($i = 1; $i <= $highestRow; $i++) {
                    $start = ord('A');
                    $temp = [];
                    for ($k = 0; $k <= $col; $k++) {
                        $temp[] =  (string)$spreadsheet->getActiveSheet()->getCell(chr($start) . $i)->getValue(); //读取类型正常
                        $start++;
                    }
                    $exc_arr[] = $temp;
                }
                return $exc_arr;
//
            }
            return false;
		}

		/**
		 * 同步附件到CDN
		 * @param $data
		 * @return string|null
		 */
		public function syncCdn($data)
		{
			$setting = Config::get('upload_attachment');
			// 数据迁移到七牛
			if ('qiniu' == $setting['driver']) {
				// 构建鉴权对象
				$auth = new QuniuAuth($setting['qiniu_access_key'], $setting['qiniu_secrect_key']);
				// 生成上传 Token
				$token = $auth->uploadToken($setting['qiniu_bucket']);
				$attachment = AttachmentModel::where('id',$data['attachment_id'])->find();
				if (!$attachment) {
					return 'fail';
				}
				// 初始化 UploadManager 对象并进行文件的上传。
				$uploadMgr = new QiniuUploadManager();
				$key = $attachment->getData('url');
				$path = $attachment['path'];
				// 上传到七牛后保存的文件名
				$key = ltrim($key, '/');
				// 调用 UploadManager 的 putFile 方法进行文件的上传。
				list($ret, $err) = $uploadMgr->putFile($token, $key, $path);
				if (isset($ret)) {
					$attachment['hash'] = $ret['hash'];
					$attachment['driver'] = 'qiniu';
					$attachment->save();
					return 'success';
				} else {
					return var_export($err, true);
				}
			} else {
				return 'fail';
			}
		}

		/**
		 * 生成保存名称
		 * @param File $file
		 * @param string $flag
		 * @return  string
		 */
		protected function buildSaveName($file, $flag = 'date')
		{
			return str_replace('/', DIRECTORY_SEPARATOR, date('Ym/d') . DIRECTORY_SEPARATOR . uniqid()) . '.' . pathinfo($file->getInfo('name'), PATHINFO_EXTENSION);
		}

	}
